package cn.tedu.csmall.sso.service.impl;

import cn.tedu.csmall.commons.exception.CoolSharkServiceException;
import cn.tedu.csmall.commons.pojo.admin.dto.AdminAddDTO;
import cn.tedu.csmall.commons.pojo.admin.dto.AdminLoginDTO;
import cn.tedu.csmall.commons.pojo.admin.model.Admin;
import cn.tedu.csmall.commons.pojo.admin.model.AdminRole;
import cn.tedu.csmall.commons.pojo.admin.vo.AdminListVO;
import cn.tedu.csmall.commons.restful.ResponseCode;
import cn.tedu.csmall.commons.utils.JwtUtils;
import cn.tedu.csmall.sso.mapper.AdminMapper;
import cn.tedu.csmall.sso.mapper.AdminRoleMapper;
import cn.tedu.csmall.sso.service.IAdminService;
import cn.tedu.csmall.sso.utils.AdminUserDetails;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
@Slf4j //提供log对象
public class AdminServiceImpl implements IAdminService {
    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AdminRoleMapper adminRoleMapper;

    @Autowired
    private AuthenticationManager authenticationManager;

    public AdminServiceImpl(){
        log.info("创建admin业务逻辑对象");
    }

    @Override
    public void addNew(AdminAddDTO adminAddDTO) {
        log.info("开始执行添加admin的业务");

        //判断用户名和密码是否为null或者空串
        if(adminAddDTO.getUsername()==null || adminAddDTO.getUsername()==""
                || adminAddDTO.getPassword()==null || adminAddDTO.getPassword()==""){
            //直接抛出异常
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"用户名或密码不能为空");
        }
        //判断用户名是否存在
        int count = adminMapper.countByUsername(adminAddDTO.getUsername());
        //count大于0，就是存在该用户
        if(count>0){
            String message = "添加管理员失败，用户名【"+adminAddDTO.getUsername()+"】已经被占用";
            log.error(message);
            throw new CoolSharkServiceException(ResponseCode.CONFLICT,message);
        }
        //以上代码都没有问题，执行新增admin的操作
        //需要将AdminAddDTO转成Admin对象
        Admin admin = new Admin();
        //利用BeanUtils工具，进行同名属性赋值
        BeanUtils.copyProperties(adminAddDTO,admin);
//        System.out.println(adminAddDTO);
//        System.out.println(admin);
        //补全adminAddDTO中没有的属性
        admin.setLoginCount(0);
        admin.setLastLoginIp(null);
        admin.setGmtCreate(LocalDateTime.now());
        admin.setGmtModified(LocalDateTime.now());
        //密码加密
        String rawPassword = admin.getPassword();
        String encodePassword = passwordEncoder.encode(rawPassword);
        admin.setPassword(encodePassword);
        //将要添加的管理员插入到数据库中
        int  adminRow = adminMapper.insert(admin);
        //如果rows==0，表示插入失败
        if(adminRow==0){
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"添加管理员失败！！！");
        }
        //新增代码
        //插入用户和角色的关联数据
        AdminRole adminRole = new AdminRole();
        //初始化数据
        adminRole.setAdminId(admin.getId());
        //暂时指定角色为2
        adminRole.setRoleId(2L);
        adminRole.setGmtCreate(LocalDateTime.now());
        adminRole.setGmtModified(LocalDateTime.now());
        log.info("管理员和角色的关联表添加管理数据adminRole:{}",adminRole);
        int rows = adminRoleMapper.insert(adminRole);
        //如果rows==0，表示插入失败
        if(rows==0){
            throw new CoolSharkServiceException(
                    ResponseCode.INTERNAL_SERVER_ERROR,
                    "添加管理员和角色中间表失败！！！");
        }
    }

    @Override
    public List<AdminListVO> list() {
        log.info("开始处理查询管理员列表的业务");
        List<AdminListVO> adminListVOS = adminMapper.list();
        return adminListVOS;
    }

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                adminLoginDTO.getUsername()
                , adminLoginDTO.getPassword());
        Authentication loginResult
                = authenticationManager.authenticate(authentication);
        // 以上调用的authenticate()方法是会抛出异常的方法，
        // 如果还能执行到此处，则表示用户名与密码是匹配的
        //登录的之后的用户信息 封装到jwt中
        // loginResult.getPrincipal() 获取的就是loadUserByUsername 返回的UserDetails对象
        AdminUserDetails user =(AdminUserDetails) loginResult.getPrincipal();
        //新增获取用户id
        Long id = user.getId();
        log.info("登录之后拿到登录的id:{}",id);
        //只获取用户名 因为密码隐私数据 不建议封装到jwt中
        String username = user.getUsername();
        log.info("登录之后拿到登录的用户名:{}",username);
        //新增获取用户权限
        Collection<GrantedAuthority> authorities = user.getAuthorities();
        //把权限信息转成JSON字符串
        String jsonAuthorities  = JSON.toJSONString(authorities);
        log.info("登录之后拿到登录的jsonAuthorities:{}",jsonAuthorities);
        //生成jwt
        HashMap<String, Object> claims = new HashMap<>();
        claims.put("id",user.getId());
        claims.put("username",user.getUsername());
        claims.put("authorities",jsonAuthorities);

        String jwt = JwtUtils.generate(claims);
        log.info("生成对应的jwt:{}",jwt);
        //返回jwt信息
        return jwt;
    }

}
